package com.member.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.member.common.enums.OrderTypeEnum;
import com.member.common.utils.DateUtils;
import com.member.common.utils.OrderNoCreate;
import com.member.common.utils.StringUtils;
import com.member.common.utils.bean.BeanUtils;
import com.member.shop.domain.*;
import com.member.shop.dto.DevelopBuyDto;
import com.member.shop.dto.FyPayDto;
import com.member.shop.dto.WxPayDto;
import com.member.shop.mapper.SysBizDevelopOrderMapper;
import com.member.shop.service.*;
import com.member.shop.vo.DevelopOrderVo;
import com.member.shop.vo.PayVo;
import org.redisson.api.RDelayedQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 发展会员数订单Service业务层处理
 *
 * @author lixinchen
 * @date 2024-01-09
 */
@Service
public class SysBizDevelopOrderServiceImpl extends ServiceImpl<SysBizDevelopOrderMapper, SysBizDevelopOrder> implements ISysBizDevelopOrderService {
    @Resource
    private SysBizDevelopOrderMapper sysBizDevelopOrderMapper;
    @Resource
    private ISysBizUserAddressService sysBizUserAddressService;
    @Resource
    private ISysBizAgreementService sysBizAgreementService;
    @Resource
    private ISysBizGoodsService sysBizGoodsService;
    @Resource
    private ISysBizGoodsSkuService sysBizGoodsSkuService;
    @Resource
    private IPayService payService;
    @Resource
    private ISysBizUserService sysBizUserService;
    @Resource
    private RDelayedQueue<String> delayedQueue;
    @Value("${rm.domain}")
    private String domain;
    /**
     * 查询发展会员数订单
     *
     * @param id 发展会员数订单主键
     * @return 发展会员数订单
     */
    @Override
    public SysBizDevelopOrder selectSysBizDevelopOrderById(Long id) {
        return sysBizDevelopOrderMapper.selectById(id);
    }

    /**
     * 查询发展会员数订单列表
     *
     * @param queryWrapper 发展会员数订单
     * @return 发展会员数订单
     */
    @Override
    public List<SysBizDevelopOrder> selectSysBizDevelopOrderList(LambdaQueryWrapper<SysBizDevelopOrder> queryWrapper) {
        return sysBizDevelopOrderMapper.selectList(queryWrapper);
    }

    /**
     * 查询发展会员数订单列表
     *
     * @param sysBizDevelopOrder 发展会员数订单
     * @return 发展会员数订单
     */
    @Override
    public List<SysBizDevelopOrder> selectSysBizDevelopOrderList(SysBizDevelopOrder sysBizDevelopOrder) {
        return sysBizDevelopOrderMapper.selectSysBizDevelopOrderList(sysBizDevelopOrder);
    }

    /**
     * 新增发展会员数订单
     *
     * @param sysBizDevelopOrder 发展会员数订单
     * @return 结果
     */
    @Override
    public int insertSysBizDevelopOrder(SysBizDevelopOrder sysBizDevelopOrder) {
        sysBizDevelopOrder.setCreateTime(DateUtils.getNowDate());
        return sysBizDevelopOrderMapper.insert(sysBizDevelopOrder);
    }

    /**
     * 修改发展会员数订单
     *
     * @param sysBizDevelopOrder 发展会员数订单
     * @return 结果
     */
    @Override
    public int updateSysBizDevelopOrder(SysBizDevelopOrder sysBizDevelopOrder) {
        sysBizDevelopOrder.setUpdateTime(DateUtils.getNowDate());
        return sysBizDevelopOrderMapper.updateById(sysBizDevelopOrder);
    }

    /**
     * 批量删除发展会员数订单
     *
     * @param ids 需要删除的发展会员数订单主键
     * @return 结果
     */
    @Override
    public int deleteSysBizDevelopOrderByIds(Long[] ids) {
        return sysBizDevelopOrderMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除发展会员数订单信息
     *
     * @param id 发展会员数订单主键
     * @return 结果
     */
    @Override
    public int deleteSysBizDevelopOrderById(Long id) {
        return sysBizDevelopOrderMapper.deleteById(id);
    }

    @Override
    public DevelopOrderVo perDevelopOrder(DevelopBuyDto developBuyDto, Long userId) {
        DevelopOrderVo developOrderVo = new DevelopOrderVo();
        SysBizUserAddress sysBizUserAddress;
        if (developBuyDto.getAddressId() == null) {
            sysBizUserAddress = sysBizUserAddressService.getOne(new LambdaQueryWrapper<SysBizUserAddress>().eq(SysBizUserAddress::getUserId, userId).eq(SysBizUserAddress::getStatus, 1));
        } else {
            sysBizUserAddress = sysBizUserAddressService.selectSysBizUserAddressById(developBuyDto.getAddressId());
        }
        if (sysBizUserAddress != null) {
            developOrderVo.setReceiveName(sysBizUserAddress.getName());
            developOrderVo.setReceivePhone(sysBizUserAddress.getPhone());
            developOrderVo.setAddress(sysBizUserAddress.getProvince() + sysBizUserAddress.getCity() + sysBizUserAddress.getArea() + sysBizUserAddress.getDetails());
            developOrderVo.setAddressId(sysBizUserAddress.getId());
        }
        SysBizAgreement sysBizAgreement = sysBizAgreementService.selectSysBizAgreementById(1L);
        developOrderVo.setNumber(developBuyDto.getNumber());
        developOrderVo.setAmount(sysBizAgreement.getCourtshipAmount().multiply(BigDecimal.valueOf(developBuyDto.getNumber())));
        if (sysBizAgreement.getCourtshipShopId() == null) {
            developOrderVo.setDevelopCover(sysBizAgreement.getMemberPic());
            return developOrderVo;
        }
        SysBizGoods sysBizGoods = sysBizGoodsService.getById(sysBizAgreement.getCourtshipShopId());
        List<SysBizGoodsSku> sysBizGoodsSkus = sysBizGoodsSkuService.selectSysBizGoodsSkuList(new LambdaQueryWrapper<SysBizGoodsSku>()
                .eq(SysBizGoodsSku::getGoodsId, sysBizGoods.getId()).eq(SysBizGoodsSku::getStatus, 0));
        developOrderVo.setGoodsCover(sysBizGoods.getCover());
        if (!CollectionUtils.isEmpty(sysBizGoodsSkus)) {
            sysBizGoodsSkus.sort(Comparator.comparing(SysBizGoodsSku::getMemberSalesPrice));
            developOrderVo.setGoodsCover(sysBizGoodsSkus.get(0).getPic());
        }
        developOrderVo.setDevelopCover(sysBizGoods.getCover());
        developOrderVo.setGoodsName(sysBizGoods.getName());
        return developOrderVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysBizDevelopOrder paymentDevelop(DevelopBuyDto developBuyDto, Long userId) {
        // 先生成未付款订单
        SysBizUser sysBizUser = sysBizUserService.selectSysBizUserById(userId);
        SysBizAgreement sysBizAgreement = sysBizAgreementService.selectSysBizAgreementById(1L);
        SysBizGoods sysBizGoods = null;
        if (sysBizAgreement.getCourtshipShopId() != null) {
            sysBizGoods = sysBizGoodsService.getById(sysBizAgreement.getCourtshipShopId());
        }
        SysBizUserAddress sysBizUserAddress = sysBizUserAddressService.selectSysBizUserAddressById(developBuyDto.getAddressId());
        BigDecimal amount = sysBizAgreement.getCourtshipAmount().multiply(BigDecimal.valueOf(developBuyDto.getNumber()));
        SysBizDevelopOrder sysBizDevelopOrder = new SysBizDevelopOrder();
        SysBizDevelopOrder developOrder = sysBizDevelopOrderMapper.selectOne(new LambdaQueryWrapper<SysBizDevelopOrder>().eq(SysBizDevelopOrder::getUserId, userId).eq(SysBizDevelopOrder::getPaymentStatus, 0));
        Date nowDate = DateUtils.getNowDate();
        long time = nowDate.getTime();
        String uniqueId = StringUtils.leftPad(userId.toString(), 8, "0") + time;
        String payId = "PAY" + uniqueId;
        if (developOrder != null) {
            sysBizDevelopOrder.setId(developOrder.getId());
            updateOrder(developBuyDto, userId, sysBizUser, sysBizGoods, sysBizUserAddress, amount, sysBizDevelopOrder, nowDate, payId);
            sysBizDevelopOrderMapper.updateById(sysBizDevelopOrder);
        } else {
            updateOrder(developBuyDto, userId, sysBizUser, sysBizGoods, sysBizUserAddress, amount, sysBizDevelopOrder, nowDate, payId);
            sysBizDevelopOrderMapper.insert(sysBizDevelopOrder);
        }
        // 将数据存入redisson队列
        String key = "DEVELOP_" + payId;
        delayedQueue.offerAsync(key, 60 * 15, TimeUnit.SECONDS);
        return sysBizDevelopOrder;
//        PayVo order = fyPayService.order(FyPayDto.builder()
//                .orderId(payId)
//                .openId(sysBizUser.getOpenId())
//                .payTime(nowDate)
//                .goodsName("发展会员商品")
//                .goodsDetail("发展会员商品明细")
//                .backNotifyUrl("https://wzapi.acmkg.com/mp-api/wx/pay/backNotifyByDevelop")
//                .amount(amount).build());
//        order.setId(sysBizDevelopOrder.getId());
//        return order;
    }

    private void updateOrder(DevelopBuyDto developBuyDto, Long userId, SysBizUser sysBizUser, SysBizGoods sysBizGoods, SysBizUserAddress sysBizUserAddress, BigDecimal amount, SysBizDevelopOrder sysBizDevelopOrder, Date nowDate, String payId) {
        String orderCode = OrderNoCreate.activityOrderCode(OrderTypeEnum.DEVELOP.name());
        sysBizDevelopOrder.setDevelopCode(orderCode);
        sysBizDevelopOrder.setAddress(sysBizUserAddress.getProvince() + sysBizUserAddress.getCity() + sysBizUserAddress.getArea() + sysBizUserAddress.getDetails());
        sysBizDevelopOrder.setAmount(amount);
        sysBizDevelopOrder.setGoodsCode(sysBizGoods == null ? "" : sysBizGoods.getGoodsCode());
        sysBizDevelopOrder.setGoodsId(sysBizGoods == null ? null : sysBizGoods.getId());
        sysBizDevelopOrder.setGoodsName(sysBizGoods == null ? "" : sysBizGoods.getName());
        sysBizDevelopOrder.setPaymentId(payId);
        sysBizDevelopOrder.setNumber(developBuyDto.getNumber());
        sysBizDevelopOrder.setOrderAddTime(nowDate);
        sysBizDevelopOrder.setStatus(0);
        sysBizDevelopOrder.setPayableAmount(amount);
        sysBizDevelopOrder.setPaymentStatus(0);
        sysBizDevelopOrder.setUserId(userId);
        sysBizDevelopOrder.setUserName(sysBizUser.getNickName());
        sysBizDevelopOrder.setPhone(sysBizUser.getUserPhone());
        sysBizDevelopOrder.setReceiveName(sysBizUserAddress.getName());
        sysBizDevelopOrder.setReceivePhone(sysBizUserAddress.getPhone());
        sysBizDevelopOrder.setCreateTime(nowDate);
        sysBizDevelopOrder.setRemark(developBuyDto.getRemark());
        sysBizDevelopOrder.setPaymentTimeEnd(DateUtils.addMinutes(DateUtils.getNowDate(), 15));
    }

    @Override
    public DevelopOrderVo queryDevelopDetail(Long id) {
        SysBizDevelopOrder sysBizDevelopOrder = sysBizDevelopOrderMapper.selectById(id);
        DevelopOrderVo developOrderVo = new DevelopOrderVo();
        BeanUtils.copyProperties(sysBizDevelopOrder, developOrderVo);
        SysBizAgreement sysBizAgreement = sysBizAgreementService.selectSysBizAgreementById(1L);
        developOrderVo.setDevelopCover(sysBizAgreement.getMemberPic());
        if (sysBizDevelopOrder.getGoodsId() != null) {
            SysBizGoods sysBizGoods = sysBizGoodsService.getById(sysBizDevelopOrder.getGoodsId());
            if (sysBizGoods != null) {
                developOrderVo.setGoodsCover(sysBizGoods.getCover());
            }
        }
        return developOrderVo;
    }

    @Override
    public List<Long> queryDevelopUserId(Long userId) {
        LambdaQueryWrapper<SysBizUser> sysBizUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysBizUserLambdaQueryWrapper.eq(SysBizUser::getParentId, userId);
        sysBizUserLambdaQueryWrapper.eq(SysBizUser::getProcessStatus, 2);
        sysBizUserLambdaQueryWrapper.eq(SysBizUser::getDeleted, 0);
        sysBizUserLambdaQueryWrapper.eq(SysBizUser::getVerifyStatus, 0);
        List<SysBizUser> sysBizUsers = sysBizUserService.selectSysBizUserList(sysBizUserLambdaQueryWrapper);
        return sysBizUsers.stream().map(SysBizUser::getId).collect(Collectors.toList());
    }

}
